package com.coai.ai.service

import com.theokanning.openai.completion.chat.ChatCompletionRequest
import com.theokanning.openai.completion.chat.ChatMessage
import com.theokanning.openai.service.OpenAiService as OpenAiClient
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Service
import java.time.Duration

/**
 * OpenAI服务封装类
 * 
 * 提供OpenAI API的核心功能调用，包括：
 * - 对话补全（Chat Completion）
 * - 流式对话
 * - 文本嵌入（Embedding）
 * - 情绪分析
 * - 关键词提取
 * - 文本摘要
 * 
 * @property apiKey OpenAI API密钥
 * @property defaultModel 默认使用的模型，默认gpt-4
 * @property timeout 请求超时时间（秒）
 */
@Service
class OpenAIService {
    
    @Value("\${openai.api-key}")
    private lateinit var apiKey: String
    
    @Value("\${openai.model:gpt-4}")
    private lateinit var defaultModel: String
    
    @Value("\${openai.timeout:60}")
    private var timeout: Long = 60
    
    private val client: OpenAiClient by lazy {
        OpenAiClient(apiKey, Duration.ofSeconds(timeout))
    }
    
    /**
     * 调用OpenAI Chat Completion API进行对话补全
     * 
     * @param messages 对话消息列表，包含角色（system/user/assistant）和内容
     * @param model 使用的模型名称，默认使用defaultModel
     * @param temperature 温度参数，控制随机性（0-2），越高越随机
     * @param maxTokens 最大生成token数
     * @return 生成的文本内容
     */
    suspend fun chatCompletion(
        messages: List<ChatMessage>,
        model: String = defaultModel,
        temperature: Double = 0.7,
        maxTokens: Int = 2000
    ): String = withContext(Dispatchers.IO) {
        
        val request = ChatCompletionRequest.builder()
            .model(model)
            .messages(messages)
            .temperature(temperature)
            .maxTokens(maxTokens)
            .build()
        
        val response = client.createChatCompletion(request)
        response.choices[0].message.content
    }
    
    /**
     * 流式输出的聊天补全
     * 
     * 支持实时流式输出AI生成的内容，适用于需要实时展示的场景
     * 
     * @param messages 对话消息列表
     * @param model 使用的模型名称
     * @param onChunk 每次接收到新内容时的回调函数
     */
    fun streamChatCompletion(
        messages: List<ChatMessage>,
        model: String = defaultModel,
        onChunk: (String) -> Unit
    ) {
        val request = ChatCompletionRequest.builder()
            .model(model)
            .messages(messages)
            .temperature(0.7)
            .stream(true)
            .build()
        
        client.streamChatCompletion(request)
            .blockingForEach { chunk ->
                chunk.choices.firstOrNull()?.message?.content?.let { content ->
                    onChunk(content)
                }
            }
    }
    
    /**
     * 将文本转换为向量表示（嵌入）
     * 
     * 用于语义搜索、相似度计算等场景
     * 使用text-embedding-ada-002模型生成嵌入向量
     * 
     * @param text 待向量化的文本
     * @return 嵌入向量（浮点数数组）
     */
    suspend fun createEmbedding(text: String): List<Double> = withContext(Dispatchers.IO) {
        val request = com.theokanning.openai.embedding.EmbeddingRequest.builder()
            .model("text-embedding-ada-002")
            .input(listOf(text))
            .build()
        
        val response = client.createEmbeddings(request)
        response.data[0].embedding
    }
    
    /**
     * 对文本进行分类
     * 
     * 使用AI将文本分类到指定的类别中
     * 
     * @param text 待分类的文本
     * @param categories 可选分类列表
     * @return 匹配的分类名称
     */
    suspend fun classifyText(
        text: String,
        categories: List<String>
    ): String = withContext(Dispatchers.IO) {
        
        val prompt = """
            请对以下文本进行分类，选择最合适的分类：
            
            文本：$text
            
            可选分类：${categories.joinToString(", ")}
            
            只返回分类名称，不要其他内容。
        """.trimIndent()
        
        val messages = listOf(
            ChatMessage("system", "你是一个文本分类助手。"),
            ChatMessage("user", prompt)
        )
        
        chatCompletion(messages, temperature = 0.3)
    }
    
    /**
     * 情绪分析
     */
    /**
     * 分析文本情绪
     * 
     * 使用AI分析文本的情绪倾向，返回情绪分数、标签和置信度
     * 
     * @param text 待分析的文本内容
     * @return 情绪分析结果，包含分数（-1到1）、情绪标签和置信度
     */
    suspend fun analyzeSentiment(text: String): SentimentResult = withContext(Dispatchers.IO) {
        
        val prompt = """
            请分析以下文本的情绪倾向，返回JSON格式：
            {"score": -1.0到1.0之间的数值, "emotion": "情绪标签", "confidence": 0.0到1.0之间的置信度}
            
            文本：$text
        """.trimIndent()
        
        val messages = listOf(
            ChatMessage("system", "你是一个情绪分析专家。"),
            ChatMessage("user", prompt)
        )
        
        val response = chatCompletion(messages, temperature = 0.3)
        
        // 解析JSON响应
        // 解析AI返回的JSON格式响应
        return try {
            // 使用正则表达式提取JSON对象
            val jsonMatch = Regex("""\{[^}]+\}""").find(response)
            if (jsonMatch != null) {
                val json = jsonMatch.value
                val scoreMatch = Regex(""""score"\s*:\s*(-?\d+\.?\d*)""").find(json)
                val emotionMatch = Regex(""""emotion"\s*:\s*"([^"]+)"""").find(json)
                val confidenceMatch = Regex(""""confidence"\s*:\s*(\d+\.?\d*)""").find(json)
                
                SentimentResult(
                    score = scoreMatch?.groupValues?.get(1)?.toDoubleOrNull() ?: 0.0,
                    emotion = emotionMatch?.groupValues?.get(1) ?: "neutral",
                    confidence = confidenceMatch?.groupValues?.get(1)?.toDoubleOrNull() ?: 0.9
                )
            } else {
                SentimentResult(score = 0.0, emotion = "neutral", confidence = 0.9)
            }
        } catch (e: Exception) {
            logger.error("Failed to parse sentiment response", e)
            SentimentResult(score = 0.0, emotion = "neutral", confidence = 0.9)
        }
    }
    
    /**
     * 提取文本中的关键词
     * 
     * 使用AI自动识别文本中的重要关键词
     * 
     * @param text 待分析的文本
     * @param maxKeywords 最多返回的关键词数量
     * @return 关键词列表
     */
    suspend fun extractKeywords(
        text: String,
        maxKeywords: Int = 10
    ): List<String> = withContext(Dispatchers.IO) {
        
        val prompt = """
            从以下文本中提取最多${maxKeywords}个关键词，用逗号分隔：
            
            $text
        """.trimIndent()
        
        val messages = listOf(
            ChatMessage("system", "你是一个关键词提取专家。"),
            ChatMessage("user", prompt)
        )
        
        val response = chatCompletion(messages, temperature = 0.3)
        response.split(",").map { it.trim() }
    }
    
    /**
     * 生成文本摘要
     * 
     * 使用AI将长文本总结为简洁的摘要
     * 
     * @param text 待总结的文本
     * @param maxLength 摘要的最大字数
     * @return 摘要文本
     */
    suspend fun summarize(
        text: String,
        maxLength: Int = 200
    ): String = withContext(Dispatchers.IO) {
        
        val prompt = """
            请将以下文本总结为不超过${maxLength}字的摘要：
            
            $text
        """.trimIndent()
        
        val messages = listOf(
            ChatMessage("system", "你是一个文本摘要专家。"),
            ChatMessage("user", prompt)
        )
        
        chatCompletion(messages)
    }
}

/**
 * 情绪分析结果
 */
data class SentimentResult(
    val score: Double,      // -1.0 (负面) 到 1.0 (正面)
    val emotion: String,    // 情绪标签
    val confidence: Double  // 置信度
)
